/*
 * FtpCode.h
 *
 *  Created on: 2012-12-25
 *      Author: yangentao@gmail.com
 */
#pragma once;
#include <string>
#include "../yet/StreamLog.h"
#include "EchoParse.h"

#define ftplog	slog<<tag("ftp")
#define ftpecho	slog<<tag("ftpecho")
#define ftpsend	slog<<tag("ftpsend")

using namespace std;

#define FTP_NONE		0
#define FTP_CONNECT		1
//RFC 959
#define FTP_USER		2
#define FTP_PASS		3
#define FTP_ACCT		4
#define FTP_CWD			5
#define FTP_CDUP		6
#define FTP_SMNT		7
#define FTP_REIN		8
#define FTP_QUIT		9
#define FTP_PORT		10
#define FTP_PASV		11
#define FTP_MODE		12
#define FTP_TYPE		13
#define FTP_STRU		14
#define FTP_ALLO		15
#define FTP_REST		16
#define FTP_STOR		17
#define FTP_STOU		18
#define FTP_RETR		19
#define FTP_LIST		20
#define FTP_NLST		21
#define FTP_APPE		22
#define FTP_RNFR		23
#define FTP_RNTO		24
#define FTP_DELE		25
#define FTP_RMD			26
#define FTP_MKD			27
#define FTP_PWD			28
#define FTP_ABOR		29
#define FTP_SYST		30
#define FTP_STAT		31
#define FTP_HELP		32
#define FTP_SITE		33
#define FTP_NOOP		34

//RFC
#define FTP_FEAT		35

#define FTP_CMD_COUNT	36


#define FTP_OK			0
#define FTP_WAIT		1
#define FTP_NEXT		2	//send the next command, RNFR/REST/USER/PASS
#define FTP_FAILED		-1
#define FTP_ERROR		-2

namespace ftp {
using namespace yet;

string ftpCmdName(int ftpCmd);

int testFtpCode(int cmd, int resultCode);
bool isFtpCmdTypeA(int cmd);
bool isFtpCmdTypeB(int cmd);

//(200.1.2.3   257) ==> 200,1,2,3,1,1
string ftpAddr(string host, u_short port);
string getIpByFtpAddr(string ftpaddr);
u_short getPortByFtpAddr(string ftpaddr);

string trimCrlf(string& s);

class FtpManager;
class Packet {
public:
	Packet();
	virtual ~Packet();
public:
	void CONNECT();
	void USER(string user);
	void PASS(string pass);
	void ACCT(string acct);
	void CWD(string pathname);
	void CDUP();
	void SMNT(string pathname);
	void QUIT();
	void REIN();
	void PORT(string host, short port);
	void PASV();
	void TYPE(string type);
	void STRU(string stru);
	void MODE(string mode);
	void RETR(string pathname);
	void STOR(string pathname);
	void STOU();
	void APPE(string pathname);
	void ALLO(string n, string n2 = "");
	void REST(string maker);
	void RNFR(string pathname);
	void RNTO(string pathname);
	void ABOR();
	void DELE(string pathname);
	void RMD(string pathname);
	void MKD(string pathname);
	void PWD();
	void LIST(string pathname = "");
	void NLST(string pathname = "");
	void SITE(string s);
	void SYST();
	void STAT(string pathname = "");
	void HELP(string s = "");
	void NOOP();
public:
	void FEAT();
public:
	string getRequest();
public:
	void appendResponse(string response);
	void clearAll();
	bool isEmptyCmd();
	string cmdName();

	bool hasResponse();
	int responseCount();
	int getCode(int index);
	vector<string> getLines(int index);
	int firstCode();
	int lastCode();
	string firstLine();
	string lastLine();
public:
	bool isOk();
	bool isNext();
	bool isFailed();
	bool isError();
	bool isWait();
public:
	//request
	int cmd;
	boost::shared_ptr<Packet> nextPacket;
public:
	//response
	string responseText;
	EchoParse responseParser;
private:
	string requestArg1;
	string requestArg2;
};

} /* namespace yet */
